package com.xht.authorization.server.oauth2.server.authorization.client;


import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;

import java.time.Duration;

/**
 * <h1>描述 ：用于管理新客户端和现有客户端和</h1>
 * <h2>它是中心组件，可以在其中注册新客户端并查询现有客户端。其他组件在遵循特定协议流时使用它，</h2>
 * <h3>例如</h3>
 * <ul>
 *     <li>客户端身份验证</li>
 *     <li>授权授予处理</li>
 *     <li>令牌自省</li>
 *     <li>动态客户端注册等</li>
 * </ul>
 * OAuth 2.0的存储库 {@link RegisteredClient}(s).
 * RegisteredClientRepository
 *
 * @author : 小糊涂
 * @version : 1.0
 * @see RegisteredClient
 **/
@Slf4j
@RequiredArgsConstructor
public class XhtRegisteredClientRepository implements RegisteredClientRepository {

    /**
     * 保存注册的客户端。
     *
     * <p>
     * 重要:敏感信息应该从实现的外部编码，例如: {@link RegisteredClient#getClientSecret()}
     *
     * @param registeredClient the {@link RegisteredClient}
     */
    @Override
    public void save(RegisteredClient registeredClient) {
        throw new RuntimeException("代码在这里执行:" + this.getClass());
    }

    /**
     * 返回由提供的{@code id}标识的注册客户端。 或{@code null}如果没有找到。
     *
     * @param id 注册标识符 如果找到，返回{@link RegisteredClient}，否则返回{@code null}
     */
    @Override
    public RegisteredClient findById(String id) {
        throw new RuntimeException("代码在这里执行:" + this.getClass());
    }

    /**
     * 根据clientId标识获取注册客户端，如果没有找到，则为空。
     *
     * @param clientId 客户端标识符
     * @return 如果找到返回{@link RegisteredClient}，否则{@code null}
     */
    @Override
    public RegisteredClient findByClientId(String clientId) {
        // todo 我们可以在这里进行业务逻辑的书写 例如利用 redis mybatis 等
        log.info("根据clientId={}标识获取注册客户", clientId);
        return RegisteredClient.withId("1234656789")
                .clientId(clientId)
                .clientSecret("{noop}secret")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                .authorizationGrantType(AuthorizationGrantType.PASSWORD)
                .redirectUri("https://www.baidu.com/")
                .scope(OidcScopes.OPENID)
                .scope(OidcScopes.PROFILE)
                .scope("read")
                .scope("write")
                .tokenSettings(TokenSettings.builder()
                        .accessTokenFormat(OAuth2TokenFormat.REFERENCE)
                        .accessTokenTimeToLive(Duration.ofSeconds(60 * 60 * 12))
                        .build())
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
                .clientAuthenticationMethods(clientAuthenticationMethods -> {
                    clientAuthenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
                    clientAuthenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_POST);
                })
                .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
                .build();
    }

}
